package com.spider.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.nio.charset.Charset;

/**
 * @author 罗振军
 * @version V1.0
 * @Package com.spider.config
 * @date 2024/7/19 14:50
 */
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {

    //定义了一个静态常量DEFAULT_CHARSET，其值为UTF-8字符集。
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private Class<T> clazz;

    /**
     * 这段代码是一个静态代码块，在Java类加载时只会执行一次。
     * 它用于设置ParserConfig的全局实例，将自动类型支持设置为true。
     * 这样在使用fastjson库进行JSON解析时，会自动识别并支持Java中的各种自定义类型，而无需手动配置。
     */
    static {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    }

    /**
     * 这段代码是一个构造函数，用于初始化FastJsonRedisSerializer类的实例。
     * 它接收一个参数clazz，用于序列化和反序列化指定类型的对象。
     *
     * @param clazz
     */
    public FastJsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    /**
     * 这段代码是一个重写的序列化方法，用于将对象转换为字节数组。
     *
     * @param t
     * @return
     * @throws SerializationException
     */
    @Override
    public byte[] serialize(T t) throws SerializationException
    {
        if (t == null)
        {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    /**
     * 这段代码是一个重写的反序列化方法，用于将字节数组转换为指定类型的对象。
     *
     * @param bytes
     * @return
     * @throws SerializationException
     */
    @Override
    public T deserialize(byte[] bytes) throws SerializationException
    {
        if (bytes == null || bytes.length <= 0)
        {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);

        return JSON.parseObject(str, clazz);
    }

    /**
     * 这段代码是一个辅助方法，用于获取指定类型的JavaType对象。
     *
     * @param clazz
     * @return
     */
    protected JavaType getJavaType(Class<?> clazz)
    {
        return TypeFactory.defaultInstance().constructType(clazz);
    }
}
